/*
 * Jenny Ruppen 09-730-391
 * Sebastien Goldberg 08-914-855
 * Henry Raymond 08-928-061
 * Stefan Mussato 09-752-270
 */
 
package ch.uzh.ifi.sopra.gruppe9.game;

import java.util.ArrayList;
import com.jme3.scene.Node;


/**
 * Screen displayed before the beginning of the game with list of all connected 
 * players where player name and color can be chosen.
 */
public class GameSetupScreen extends Node implements IUpdatable {
	
	
	/**
	 * List of all registered mouseOver event elements of the game setup screen.
	 */
	private ArrayList<IMouseOverable> mouseOverables = new ArrayList<IMouseOverable>();
	
	
	/**
	 * List of all registered click event elements of the game setup screen.
	 */
	private ArrayList<IClickable> clickables = new ArrayList<IClickable>();
	
	
	/**
	 * List of all registered mouseOver event elements of the name and color window.
	 */
	private ArrayList<IMouseOverable> nameColorWindowMouseOverables = new ArrayList<IMouseOverable>();
	
	
	/**
	 * List of all registered click event elements of the name and color window.
	 */
	private ArrayList<IClickable>  nameColorWindowClickables = new ArrayList<IClickable>();
	
	
	/**
	 * Geometry node of all content on the screen.
	 */
	private Node screen;
	
	
	/**
	 * Text displaying the address of the host to which the player is connected to.
	 */
	private GuiText connectedTo;
	
	
	/**
	 * List of player names.
	 */
	private GuiText[] playerNameList = new GuiText[4];
	
	
	/**
	 * List of players are ready or not.
	 */
	private GuiText[] playerReadyList = new GuiText[4];
	
	
	/**
	 * List of players colors.
	 */
	private GuiQuad[] playerColorList = new GuiQuad[4];
	
	
	/**
	 * Shades of the user's line in the list of players.
	 */
	private GuiQuad playerListShade;
	
	
	/**
	 * Text displaying that game is waiting for second player to connect.
	 */
	private GuiText waitingForSecondPlayer;
	
	
	/**
	 * Change name / color button.
	 */
	private GuiButton changeNameColorButton;
	
	
	/**
	 * Set player as ready
	 */
	private GuiButton iAmReady;
	
	
	/**
	 * Text displaying that game is waiting for all players to be ready.
	 */
	private GuiText waitingForOtherPlayers;

	
	/**
	 * Window where the player can choose name and color.
	 */
	private Node nameColorWindow;
	
	
	/**
	 * Text input field for changing name in name and color window.
	 */
	private GuiTextInput name;
	
	
	/**
	 * Selection for player's color in name and color window.
	 */
	private GuiSelection color;
	
	
	/**
	 * OK button of the name and color window.
	 */
	private GuiButton nameColorWindowOk;
	
	
	/**
	 * Window displaying message that the game is starting.
	 */
	private Node gameStarting;
	
	
	/**
	 * Countdown before game starts to create a fake sense of game build-up time.
	 */
	private float gameStartCountdown;
	
	
	/**
	 * Constructor: Creates geometry.
	 */
	public GameSetupScreen() {
		
		screen = new Node();
		
		GuiQuad background = new GuiQuad();
		background.setPositionSize(GUI.Offset.WINDOW, 0, 0, GUI.getScaledWindowWidth(), 768, 0);
		background.setMaterial(MaterialManager.getMarble(), 0.0f, 0.0f, 0.0019531275f * GUI.getScaledWindowWidth(), 1.5f);
		screen.attachChild(background.create());
		
		GuiQuad logo = new GuiQuad();
		logo.setPositionSize(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() / 2) - 160, 0, 320, 240, 1);
		logo.setMaterial(MaterialManager.getLogo(), 0.0f, 0.0f, 1.0f, 1.0f);
		screen.attachChild(logo.create());
		
		GuiWindow playerListWindow = new GuiWindow(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() / 2) - 380, 240, 760, 485, 1);
		screen.attachChild(playerListWindow);
		
		connectedTo = new GuiText("");
		screen.attachChild(connectedTo);
		
		GuiText playerListTitleText = new GuiText("Verbundene Spieler");
		playerListTitleText.setPositionSize(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() / 2) - 300, 335, 2);
		screen.attachChild(playerListTitleText);
		
		GuiBox playerListBox = new GuiBox(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() / 2) - 300, 360, 600, 160, 3);
		screen.attachChild(playerListBox);
		
		for(int i = 0; i < 4; i++) {
			playerNameList[i] = new GuiText("");
			playerNameList[i].setPositionSize(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() / 2) - 260, 370 + (i * 40), 4);
			screen.attachChild(playerNameList[i]);
			playerReadyList[i] = new GuiText("");
			playerReadyList[i].setPositionSize(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() / 2) + 290 - GuiText.getTextWidth("Spielbereit", Fonts.getNormal()), 370 + (i * 40), 4);
			screen.attachChild(playerReadyList[i]);
			playerColorList[i] = new GuiQuad();
			playerColorList[i].setPositionSize(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() / 2) - 300, 360 + (i * 40), 40, 40, 4);
			playerColorList[i].setMaterial(MaterialManager.getPlayerColors(), 0.0f, 0.0f, 0.08333f, 1.0f);
			playerColorList[i].create();
		}
		
		playerListShade = new GuiQuad();
		playerListShade.setMaterial(MaterialManager.getShade(), 0.0f, 0.0f, 1.0f, 1.0f);
		
		waitingForSecondPlayer = new GuiText("Warten auf zweiten Spieler...");
		waitingForSecondPlayer.setPositionSize(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() / 2) - 290, 410, 4);
		screen.attachChild(waitingForSecondPlayer);
		
		changeNameColorButton = new GuiButton("Name & Farbe \u00E4ndern");
		changeNameColorButton.setPositionSize(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() / 2) - 300, 535, 220, 2);
		changeNameColorButton.setAction(new ICallback() { 
			public void run() { 
				changeNameColorButton.setActive(false);
				iAmReady.setActive(false);
				screen.attachChild(nameColorWindow);
				GUI.registerMouseOverable(nameColorWindowMouseOverables);
				GUI.registerClickable(nameColorWindowClickables);
			}
		});
		screen.attachChild(changeNameColorButton.create());	
		
		iAmReady = new GuiButton("Ich bin spielbereit!");
		iAmReady.setPositionSize(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() / 2) - 150, 640, 300, 2);
		iAmReady.setAction(new ICallback() { 
			public void run() { 
				Game.board().me().setReady(true);
				GUI.unregisterMouseOverable(mouseOverables);
				GUI.unregisterClickable(clickables);
				if(screen.hasChild(iAmReady)) {
					screen.detachChild(iAmReady);
				}
				screen.attachChild(waitingForOtherPlayers);
				changeNameColorButton.setActive(false);
			}
		});
		screen.attachChild(iAmReady.create());
		
		waitingForOtherPlayers = new GuiText("Warten bis alle Spieler bereit sind...");
		waitingForOtherPlayers.setPositionSize(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() - (int)waitingForOtherPlayers.getLineWidth()) / 2, 650, 2);
		
		clickables.add(changeNameColorButton);
		clickables.add(iAmReady);
		
		mouseOverables.add(changeNameColorButton);
		mouseOverables.add(iAmReady);
		
		
		// Name and Color window
		
		nameColorWindow = new Node();
		
		ICallback submitNameColorWindow = new ICallback() { 
			public void run() { 
				GUI.unregisterMouseOverable(nameColorWindowMouseOverables);
				GUI.unregisterClickable(nameColorWindowClickables);
				if(screen.hasChild(nameColorWindow)) {
					screen.detachChild(nameColorWindow);
				}
				changeNameColorButton.setActive(true);
				iAmReady.setActive(true);
				Game.board().me().setName(name.getValue());
				Game.board().me().setColor(color.getValue());
			}
		};
		
		GuiWindow nameColorWindowWindow = new GuiWindow(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() / 2) - 235, 285, 470, 395, 10);
		nameColorWindow.attachChild(nameColorWindowWindow);
		
		GuiText nameTitle = new GuiText("Name:");
		nameTitle.setPositionSize(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() / 2) - 150, 330, 11);
		nameColorWindow.attachChild(nameTitle);
		
		name = new GuiTextInput("");
		name.setPositionSize(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() / 2) - 150, 355, 300, 11);
		name.setAction(submitNameColorWindow);
		nameColorWindow.attachChild(name.create());
		
		GuiText colorTitle = new GuiText("Farbe:");
		colorTitle.setPositionSize(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() / 2) - 150, 430, 11);
		nameColorWindow.attachChild(colorTitle);
		
		color = new GuiSelection(false, false);
		for(int i = 0; i < 12; i++) {
			color.addOption(i, GUI.Offset.WINDOW, ((GUI.getScaledWindowWidth() / 2) - 150 + ((i * 52) % 312)) , 455 + (52 * (i / 6)), 40, 40, 12);
			
			GuiQuad possiblePlayerColor = new GuiQuad();
			possiblePlayerColor.setPositionSize(GUI.Offset.WINDOW, ((GUI.getScaledWindowWidth() / 2) - 150 + ((i * 52) % 312)) , 455 + (52 * (i / 6)), 40, 40, 13);
			possiblePlayerColor.setMaterial(MaterialManager.getPlayerColors(), i * 0.08333f, 0.0f, 0.08333f, 1.0f);
			nameColorWindow.attachChild(possiblePlayerColor.create());
		}
		nameColorWindow.attachChild(color);
		
		nameColorWindowOk = new GuiButton("OK");
		nameColorWindowOk.setPositionSize(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() / 2) - 100, 590, 200, 11);
		nameColorWindowOk.setAction(submitNameColorWindow);
		nameColorWindow.attachChild(nameColorWindowOk.create());
		
		nameColorWindowClickables.add(nameColorWindowOk);
		nameColorWindowClickables.add(name);
		nameColorWindowClickables.addAll(color.getClickables());
		
		nameColorWindowMouseOverables.add(nameColorWindowOk);
		nameColorWindowMouseOverables.addAll(color.getMouseOverables());
		
		
		// Game starting window
		
		gameStarting = new Node();
		
		GuiText gameStartingText = new GuiText("Spiel startet...");
		gameStartingText.setPositionSize(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() - (int)gameStartingText.getLineWidth()) / 2, 472, 11);
		gameStarting.attachChild(gameStartingText);
		
		GuiWindow gameStartingWindow = new GuiWindow(GUI.Offset.WINDOW, ((GUI.getScaledWindowWidth() - (int)gameStartingText.getLineWidth()) / 2) - 85, 427, (int)gameStartingText.getLineWidth() + 170, 110, 10);
		gameStarting.attachChild(gameStartingWindow);
		
		

	}
	
	
	/**
	 * Attach all needed geometry and register all mouseOver and click events.
	 */
	public void show() {
		
		connectedTo.setText("Verbunden mit: " + Connection.getIP());
		connectedTo.setPositionSize(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() - (int)connectedTo.getLineWidth()) / 2, 290, 1);
		
		updatePlayerList();
		
		this.attachChild(screen);
		GUI.registerMouseOverable(mouseOverables);
		GUI.registerClickable(clickables);
		
		name.setValue(Game.board().me().getName());
		color.setInitialValue(Game.board().me().getColor());
	}
	
	
	/**
	 * Detach all geometry and unregister all mouseOver and click events.
	 */
	public void hide() {
		this.detachChild(screen);
		GUI.unregisterMouseOverable(mouseOverables);
		GUI.unregisterClickable(clickables);
	}


	/**
	 * Updates list of players when the server sends a update message.
	 */
	public void updatePlayerList() {
		PlayerStub player;
		for(int i = 0; i < Game.board().getPlayerNum(); i++) {
			player = Game.board().getPlayer(i);
			String playerName = GuiText.getCroppedText(player.getName(), Fonts.getNormal(), 450);
			playerNameList[i].setText(playerName);
			if(player.isReady()) {
				playerReadyList[i].setText("Spielbereit");
			}
			if(!screen.hasChild(playerColorList[i])) {
				screen.attachChild(playerColorList[i]);
			}
			playerColorList[i].changeTextureCoords(player.getColor() * 0.08333f, 0.0f, 0.08333f, 1.0f);
		}
		if(!screen.hasChild(playerListShade)) {
			playerListShade.setPositionSize(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() / 2) - 300, 360 + (Game.board().getMyIndex() * 40), 600, 40, 2);
			playerListShade.create();
			screen.attachChild(playerListShade);		
		}
		if(Game.board().getPlayerNum() >= 2 && screen.hasChild(waitingForSecondPlayer)) {
			screen.detachChild(waitingForSecondPlayer);
		}
	}

	
	/**
	 * Displays a message that the game is starting.
	 */
	public void gameStarting() {
		screen.detachChild(waitingForOtherPlayers);
		screen.attachChild(gameStarting);
		gameStartCountdown = 2.0f;
		GUI.registerUpdatable(this);
	}
	
	
	@Override
	public void update(float delta) {
		gameStartCountdown -= delta;
		if(gameStartCountdown < 0.0f) {
			GUI.unregisterUpdatable(this);
			GUI.changeState(GuiState.State.CLEAN_INGAME_SCREEN);
		}
	}
	
}
